package com.franklin.ideaplugin.easytesting.listener;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.franklin.ideaplugin.easytesting.constant.Constants;
import com.franklin.ideaplugin.easytesting.javaagent.AgentUtils;
import com.google.common.collect.Lists;
import com.intellij.execution.*;
import com.intellij.execution.configurations.*;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.Project;
import com.intellij.util.PathsList;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.util.*;


/**
 * 插入自定义jar包
 *
 * @author Ye Junhui
 * @since 2023/6/3
 */
public class EasyTestingAppLifeCycleListener implements ExecutionListener {

    private static final List<String> agentPathList = new ArrayList<>();

    static {
        IdeaPluginDescriptor enabledPlugin = PluginManager.getInstance().findEnabledPlugin(PluginId.getId("com.franklin.ideaplugin.easy-testing"));
        String pluginPath = enabledPlugin.getPluginPath().toString();
        pluginPath = pluginPath.replace("\\", "/");
        File libDir = FileUtil.file(pluginPath + "/lib/");
        if (Objects.nonNull(libDir) && libDir.isDirectory()) {
            for (File file : libDir.listFiles()) {
                String fileName = file.getName();
                if (fileName.endsWith(Constants.AGENT_SUFFIX)) {
                    if (fileName.startsWith(Constants.AGENT_NAME)) {
                        agentPathList.add(pluginPath + "/lib/" + fileName);
                    }else if (fileName.startsWith(Constants.JAVA_AGENT_NAME)) {
                        agentPathList.add(pluginPath + "/lib/" + fileName);
                    }
                }
            }
        }
    }

    @Override
    public void processStartScheduled(@NotNull String executorId, @NotNull ExecutionEnvironment env) {
        CommonJavaRunConfigurationParameters springBootApplicationRunConfiguration = getSpringConfiguration(env);
        if (Objects.isNull(springBootApplicationRunConfiguration)) {
            return;
        }
        try {
            RunProfileState state = env.getState();
            if (state instanceof JavaCommandLineState) {
                JavaCommandLineState javaCommandLineState = (JavaCommandLineState) state;
                JavaParameters javaParameters = javaCommandLineState.getJavaParameters();
                PathsList classPath = javaParameters.getClassPath();
                List<String> classPathList = classPath.getPathList();
                //无web依赖
                if (classPathList.stream().noneMatch(cp -> cp.contains("spring-web"))){
                    return;
                }
                if (classPathList.stream().noneMatch(cp -> cp.contains(Constants.AGENT_NAME))) {
                    String javaAgentPath = agentPathList.stream().filter(path -> path.contains("java-agent"))
                            .findFirst()
                            .orElse("");
                    if (StrUtil.isNotBlank(javaAgentPath)){
                        List<String> tempAgentList = Lists.newArrayList(agentPathList);
                        tempAgentList.removeIf(path -> path.contains("java-agent"));
                        if (classPathList.stream().anyMatch(cp -> cp.contains("starter-webflux"))) {
                            //webflux
                            tempAgentList.removeIf(agent -> agent.contains("-web-"));
                        } else {
                            //web
                            tempAgentList.removeIf(agent -> agent.contains("-webflux-"));
                        }
                        //清除上次的jvm参数
                        String vmParameters = cleanVmParameters(springBootApplicationRunConfiguration.getVMParameters());

                        //插入参数
                        if (CollectionUtil.isNotEmpty(tempAgentList) && !vmParameters.contains(Constants.JAVA_AGENT_NAME)){
                            String newVmParam = vmParameters + " " + buildAgentCommand(
                                    springBootApplicationRunConfiguration.getProject(),
                                    javaAgentPath,
                                    tempAgentList
                            );
                            springBootApplicationRunConfiguration.setVMParameters(newVmParam);
                        }
                    }
                }
            }
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    /**
     * 构建javaagent命令
     * @param javaAgentPath
     * @param agentPathList
     * @return
     */
    private String buildAgentCommand(Project project,String javaAgentPath,List<String> agentPathList){
        String basePath = project.getBasePath();
        if (StrUtil.isBlank(basePath)){
            return "";
        }
        basePath = basePath.replace('\\','/');
        AgentUtils.buildAgentOps(basePath,agentPathList);
        return String.format("-javaagent:\"%s\"", javaAgentPath);
    }

    private CommonJavaRunConfigurationParameters getSpringConfiguration(ExecutionEnvironment env) {
        RunnerAndConfigurationSettings runnerAndConfigurationSettings = env.getRunnerAndConfigurationSettings();
        if (Objects.isNull(runnerAndConfigurationSettings)){
            return null;
        }
        String uniqueID = runnerAndConfigurationSettings.getUniqueID();
        if (!uniqueID.startsWith("Spring Boot")){
            return null;
        }
        RunConfiguration configuration = runnerAndConfigurationSettings.getConfiguration();
        if (!(configuration instanceof CommonJavaRunConfigurationParameters)) {
            return null;
        }
        return (CommonJavaRunConfigurationParameters) configuration;
    }


    /**
     * 去除jvm参数
     * @param originVm
     * @return
     */
    private String cleanVmParameters(String originVm){
        if (StrUtil.isBlank(originVm)){
            return "";
        }
        int index = originVm.indexOf(Constants.JAVA_AGENT_NAME);
        if (index < 0){
            return originVm;
        }
        String leftString = originVm.substring(0, index);
        String rightString = originVm.substring(index + Constants.JAVA_AGENT_NAME.length());
        int agentCommandIndex = leftString.lastIndexOf("-javaagent");
        int commandEndIndex = rightString.indexOf('"') + index + Constants.JAVA_AGENT_NAME.length();

        //修复字符串
        String l = originVm.substring(0, agentCommandIndex);
        String r = originVm.substring(commandEndIndex + 1);
        return l + r;
    }
}
